// https://blog.golang.org/go1.13-errors
package main

import (
	"errors"
	"fmt"
)

var (
	errPermission = errors.New("no auth")
)

// 自定义error 类型
type queryError struct {
	Query string
	Err error
}

func (e *queryError) Error() string {
	return e.Query + ":" + e.Err.Error()
}

func tErrorHandling() {
	err := &queryError{
		Query: "open file",
		Err: errors.New("invalid file"),
	}

	var err2 error
	err2 = *&err
	fmt.Printf("err: %v", err2)

	// 在 1.13之前 是这样unwrap 底层的error的
	if e, ok := err2.(*queryError); ok && e.Err == errPermission {
		fmt.Printf("err permission")
	}

	// 1.13有Is 方法
	// 这是考察err2 的error chain中是否有target error
	if errors.Is(err2, errPermission) {

	}

	var e *queryError
	// 检验error 是否是queryError类型的error
	if errors.As(err, &e) {

	}

	// 1.13提供了 Unwrap 方法，当fmt.Errorf中使用 %w verb时，返回的error就会把 底层error 给wrap
	err3 := fmt.Errorf("access denied: %w", errPermission)
	// wrap 之后，有利于调用 Is, As
	if errors.Is(err3, errPermission) {

	}

	// 关于是否要wrap 
	// 这取决于error创建时的上下文，有必要暴露给caller就 wrap
}